/****************************************************************************************
 * File:			Component.cs
 * Description:		Definition of a component and related import / export facilities.
 ***************************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;

namespace XGAE.Framework
{
    /// <summary>
    /// An instance of an AI module in the architecture.  Contains other components within the 
    /// scope, and handles their processing hierarchically for most of the operations defined.
    /// </summary>
    public class Component : IDisposable
    {
        #region Fields

        protected string m_type; // helper string representing the exporter type

        /// <summary>
        /// Determine the type of this component.
        /// </summary>
        public string Type
        {
            get { return this.m_type; }
        }

        protected Architecture m_parent; // parent architecture, if any

        // Track whether Dispose has been called.
        private bool disposed = false;

        #endregion

        #region C'tors

        /// <summary>
        /// Constructor called by the class factory when it creates a new component.
        /// </summary>
        /// <param name="type">String representing the type that the factory created.</param>
        public Component(string type)
        {
            this.m_type = type;
            this.m_parent = null;
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Internalise the data stored within the XML, and perform preliminary preparations.
        /// This is generally automatically generated with FEAR tools.	    
        /// </summary>
        /// <param name="config">Relevant DOM node of the entire XML document.</param>
        public virtual void Load(Extensions.XmlDataTree config) { }

        /// <summary>
        /// Overloaded function that prepares the loading as appropriate.
        /// </summary>
        /// <param name="config"></param>
        /// <param name="parent"></param>
        public virtual void PreLoad(Extensions.XmlDataTree config, Architecture parent)
        {
            // standard components just load themselves
            this.Load(config);
        }

        /// <summary>
        /// Initialisation is called after the Load() procedure to add finishing touches. 
        /// Usually coded by hand by the developer.
        /// </summary>
        public virtual void Init() { }

        /// <summary>
        /// Selective persistence modifies the nodes in the XML only as appropriate.
        /// </summary>
        /// <param name="config">Relevant DOM node of the entire XML document.</param>
        public virtual void Save(Extensions.XmlDataTree config) { }

        /// <summary>
        /// Overloaded function that prepares the saving.
        /// </summary>
        /// <param name="config"></param>
        public virtual void PreSave(Extensions.XmlDataTree config)
        {
            // standard components just load themselves
            this.Save(config);
        }

        /// <summary>
        /// Called before the Save procedure to prepare for automatic storage.  Usually coded by 
        /// hand by the developer.
        /// </summary>
        public virtual void Done() { }

        /// <summary>
        /// Add a component to the scope if possible.  This will generally be done by 
        /// architectures only, so that they can pass the Body and other global components around.
        /// </summary>
        /// <param name="name">String representing the name of the component.</param>
        /// <param name="component">Pointer to the component to be added.</param>
        public virtual void Include(string name, Component component) { }

        /// <summary>
        /// Implemented by components that need to listen to messages.
        /// </summary>
        /// <param name="m">The message received, it can be upcast back. </param>
        public virtual void Dispatch(Message message) { }

        /// <summary>
        /// Implemented by components that need to emmit messages.
        /// </summary>
        /// <param name="message">A downcast message that must be sent.</param>
        public virtual void Broadcast(Message message)
        {
            if (this.m_parent!=null)
                this.m_parent.Broadcast(message);
        }

        #region Interface Management

        /// <summary>
        /// Virtual implementation of interface handling.  This can optionally be overriden 
        /// for components that need to import interfaces.
        /// </summary>
        /// <param name="name">Name of the hook under which to import the interface.</param>
        /// <param name="i">Referense to the interface itself.</param>
        /// <returns>Indication of success.</returns>
        public virtual bool Import(string name, Interface i)
        {
            return false;
        }

        /// <summary>
        /// Virtual implementation of the interface creation within the component.
        /// This must be overriden for exporters expected to provide interfaces.
        /// </summary>
        /// <param name="name">Name of the interface in question.</param>
        /// <returns>A refernse to a new interface, to be cast upwards at will.</returns>
        public virtual Interface Export(string name)
        {
            /*throw fear.Exception("Abstract component " + m_type +
                " does not implement Export().  No interface found with name "
                + name + ".", __FILE__, __LINE__);*/

            return null;
        }

        #endregion

        #endregion

        #region IDisposable Methods

        // Implement IDisposable.
        // Do not make this method virtual.
        // A derived class should not be able to override this method.
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // If disposing equals false, the method has been called by the
        // runtime from inside the finalizer and you should not reference
        // other objects. Only unmanaged resources can be disposed.
        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!this.disposed)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if (disposing)
                {
                    // Dispose managed resources.
                    // tell the registry to free the brain
                }

                // Note disposing has been done.
                disposed = true;
            }
        }

        // Use C# destructor syntax for finalization code.
        // This destructor will run only if the Dispose method
        // does not get called.
        // It gives your base class the opportunity to finalize.
        // Do not provide destructors in types derived from this class.
        ~Component()
        {
            // Do not re-create Dispose clean-up code here.
            // Calling Dispose(false) is optimal in terms of
            // readability and maintainability.
            Dispose(false);
        }

        #endregion
    }

    /*class MyModule : Factory											
    {
    }*/
}
